package org.hismig.partition.mssqlserver;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.dbcp.BasicDataSource;
import org.hismig.cfg.DBConnection;
import org.hismig.cfg.DynamicPartition;
import org.hismig.cfg.partition.Configuration;
import org.hismig.partition.IDynamicPartition;
import org.hismig.partition.PartitionBase;
import org.hismig.utils.DateTool;
import org.hismig.utils.JDBCTool;
import org.hismig.utils.StringTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @declare: //TODO <br />
 *           This class created by Vansion.Hopihit on 2012-07-04 <br />
 *           <a href="mailto:vansionhopihit@gmail.com">Contact Me</a>
 * @version 1.0
 * @author Vansion.Hopihit
 * 
 */
public class DayPartition extends PartitionBase {

	private static Logger logger = LoggerFactory.getLogger(DayPartition.class);

	protected static final String K_SCOPE = "scope";
	protected static final String K_DB_PATH = "db_path";
	protected static final String K_DAT_SIZE = "dat_size";
	protected static final String K_DAT_MAXSIZE = "dat_maxsize";
	protected static final String K_DAT_FILEGROWTH = "dat_filegrowth";
	protected static final String K_LOG_SIZE = "log_size";
	protected static final String K_LOG_MAXSIZE = "log_maxsize";
	protected static final String K_LOG_FILEGROWTH = "log_filegrowth";

	protected static final String EXPRESSION = "'#{CURRENTDAY}' ge '%s' and '#{CURRENTDAY}' lt '%s'";
	protected int scope;

	protected String db_path = "";
	protected String dat_size = "";
	protected String dat_maxsize = "";
	protected String dat_filegrowth = "";
	protected String log_size = "";
	protected String log_maxsize = "";
	protected String log_filegrowth = "";

	@Override
	protected DBConnection makeNewDBConnection(int index) throws SQLException {

		String dbName = getRealDBName(index);

		logger.debug(String.format("Start to check and create DataBase[:%s]",
				dbName));
		createNewDataBase(dbName);
		logger.debug(String.format("Check and create DataBase[:%s] completely",
				dbName));

		String today = DateTool.getNormalDate(new Date());
		String nextDay = DateTool.getNormalDate(DateTool.CountDate(scope));

		String selection = String.format(EXPRESSION, new Object[]{today,
				nextDay});
		logger.debug(String.format(
				"Auto create Selection Expression[:%s] completely", selection));

		Map<String, String> paramsMap = new HashMap<String, String>();

		paramsMap.put(IDynamicPartition.KEY_SELECTION, selection);
		paramsMap.put(IDynamicPartition.KEY_DRIVER, driver);
		paramsMap.put(IDynamicPartition.KEY_URL, getRealDBUrl(index));
		paramsMap.put(IDynamicPartition.KEY_USER, dynamicPartition
				.getParamByName(IDynamicPartition.KEY_USER));
		paramsMap
				.put(IDynamicPartition.KEY_PASSWORD, dynamicPartition
						.getParamByName(IDynamicPartition.KEY_PASSWORD));

		return Configuration.makeDBConnection(paramsMap,
				dynamicPartition.isEncrypt());
	}

	protected void createNewDataBase(String dbName) throws SQLException {
		// just execute once, so do not need to create a pool

		BasicDataSource ds = new BasicDataSource();
		ds.setDriverClassName(driver);
		ds.setUrl(createDBUrl);
		ds.setUsername(user);
		ds.setPassword(password);

		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;

		try {
			conn = ds.getConnection();

			stmt = conn.createStatement();

			logger.debug(String.format(
					"Start to check Database[:%s] if exists", dbName));
			rs = stmt.executeQuery(getCheckDBExistsSql(dbName));

			if (!rs.next()) {
				logger.info(String
						.format("Check Database[:%s] if exists completely, result[:%s]",
								new Object[]{dbName, false}));
				stmt.executeUpdate(getCreateSql(dbName));
				logger.info(String.format("Create Database[:%s] completely",
						dbName));
			} else {
				logger.info(String
						.format("Check Database[:%s] if exists completely, result[:%s]",
								new Object[]{dbName, true}));
			}

		} catch (SQLException e) {
			logger.error(String.format("Can't create new Database[:%s] : %s",
					new Object[]{dbName, e.toString()}));
			throw new SQLException(String.format(
					"Can't create new Database[:%s] : %s", new Object[]{dbName,
							e.toString()}), e);

		} finally {
			JDBCTool.closeQuietly(conn, stmt, rs);
			try {
				ds.close();
			} catch (SQLException e) {
			}
		}

	}

	protected String getCheckDBExistsSql(String dbName) {
		return String.format("SELECT 1 FROM SYSDATABASES WHERE NAME='%s'",
				dbName);
	}

	protected String getCreateSql(String dbName) {

		StringBuffer sql = new StringBuffer();

		sql.append("CREATE DATABASE ").append(dbName);
		sql.append(" ON");
		sql.append("(");
		sql.append("NAME=").append(dbName).append("_dat");

		if (!StringTool.isEmpty(db_path)) {
			sql.append(",");
			sql.append("FILENAME='").append(db_path).append(dbName)
					.append(".mdf'");
		}

		if (!StringTool.isEmpty(dat_size)) {
			sql.append(",");
			sql.append("SIZE=").append(dat_size);
		}

		if (!StringTool.isEmpty(dat_maxsize)) {
			sql.append(",");
			sql.append("MAXSIZE=").append(dat_maxsize);
		}

		if (!StringTool.isEmpty(dat_filegrowth)) {
			sql.append(",");
			sql.append("FILEGROWTH=").append(dat_filegrowth);
		}
		sql.append(")");

		sql.append(" LOG ON");
		sql.append("(");

		sql.append("NAME=").append(dbName).append("_log");

		if (!StringTool.isEmpty(db_path)) {
			sql.append(",");
			sql.append("FILENAME='").append(db_path).append(dbName)
					.append(".ldf'");
		}

		if (!StringTool.isEmpty(log_size)) {
			sql.append(",");
			sql.append("SIZE=").append(log_size);
		}

		if (!StringTool.isEmpty(log_maxsize)) {
			sql.append(",");
			sql.append("MAXSIZE=").append(log_maxsize);
		}

		if (!StringTool.isEmpty(log_filegrowth)) {
			sql.append(",");
			sql.append("FILEGROWTH=").append(log_filegrowth);
		}

		sql.append(")");

		logger.debug(String.format("Get create DataBase[:%s] sql : %s",
				new Object[]{dbName, sql.toString()}));

		return sql.toString();
	}

	@Override
	protected void setDynamicPartitonEx(DynamicPartition dynamicPartition) {

		scope = StringTool.getIntFormString(dynamicPartition
				.getParamByName(K_SCOPE));

		db_path = StringTool.replacePath(dynamicPartition
				.getParamByName(K_DB_PATH));
		if (StringTool.isEmpty(db_path)) {
			logger.warn(String.format("Argument[:%s] is empty", K_DB_PATH));
		}

		dat_size = dynamicPartition.getParamByName(K_DAT_SIZE);
		if (StringTool.isEmpty(dat_size)) {
			logger.warn(String.format("Argument[:%s] is empty", K_DAT_SIZE));
		}

		dat_maxsize = dynamicPartition.getParamByName(K_DAT_MAXSIZE);
		if (StringTool.isEmpty(dat_maxsize)) {
			logger.warn(String.format("Argument[:%s] is empty", K_DAT_MAXSIZE));
		}

		dat_filegrowth = dynamicPartition.getParamByName(K_DAT_FILEGROWTH);
		if (StringTool.isEmpty(dat_maxsize)) {
			logger.warn(String.format("Argument[:%s] is empty",
					K_DAT_FILEGROWTH));
		}

		log_size = dynamicPartition.getParamByName(K_LOG_SIZE);
		if (StringTool.isEmpty(log_size)) {
			log_size = dat_size;
			logger.debug(String.format(
					"Argument[:%s] is empty, auto use Argument[:%s]=%s",
					new Object[]{K_LOG_SIZE, K_DAT_SIZE, dat_size}));
		}

		log_maxsize = dynamicPartition.getParamByName(K_LOG_MAXSIZE);
		if (StringTool.isEmpty(log_maxsize)) {
			log_maxsize = dat_maxsize;
			logger.debug(String.format(
					"Argument[:%s] is empty, auto use Argument[:%s]=%s",
					new Object[]{K_LOG_MAXSIZE, K_DAT_MAXSIZE, dat_maxsize}));
		}

		log_filegrowth = dynamicPartition.getParamByName(K_LOG_FILEGROWTH);
		if (StringTool.isEmpty(log_filegrowth)) {
			log_filegrowth = dat_filegrowth;
			logger.debug(String.format(
					"Argument[:%s] is empty, auto use Argument[:%s]=%s",
					new Object[]{K_LOG_FILEGROWTH, K_DAT_FILEGROWTH,
							dat_filegrowth}));
		}

	}

}
